﻿/*
说明：多功能表格插件

使用方式：

var ultraTable;

$(function () {

var options = {
Container: $("#divTable"),
Css: "tblStyle1",
Columns: [
{ name: "序号", style: "width:100px", dataFiled: "sno", type: "text" },
{ name: "名称", style: "width:100px", dataFiled: "name", type: "textbox" },
{ name: "操作", style: "width:200px", type: "button", buttons: [{ name: "编辑", event: "edit" }, { name: "删除", event: "delete" }, { name: "插入", event: "insert"}] }
],
saveEvent: tableSaveEvent,   //设置点击保存按钮的操作方法
deleteEvent:tableDeleteEvent  //设置点击删除按钮的操作方法
};

var data = [{ sno: 1, name: "张三" }, { sno: 2, name: "李四"}];

ultraTable = $("#divTable").ultraTable(options);
ultraTable.bindData(data);
})

//表格保存委托事件
function tableSaveEvent(src, data) {
ultraTable.cancelEdit(src);
alert(data.name);
}
        
//表格删除委托事件
function tableDeleteEvent(src, data) {
alert("删除" + data.name);
ultraTable.deleteRow(src);
}


*/
$.fn.ultraTable = function (options) {
    var defaults = {
        //公有属性，由用户自己设置
        DataSource: null, 		//数据源
        Columns: [{ name: "head", display: false, dataFiled: "", width: 0, type: "text"}], 	//表格头列名，是一个数组  var column : new Array(),  当显示状态为Table才起作用
        Container: null, //容器 在什么地方创建表格
        Buttons: null,  //底部现实的按钮
        Table: null, //表格对象
        saveEvent: null, //行保存事件  saveEvent(src,data,object)  src 源触发对象，data 数据json格式，object 当前插件对象
        deleteEvent: null, //行删除事件
        datePickerEvent: null, //日期控件选择绑定事件
        dblclickToEdit: false //是否双击行进入编辑状态
    } //默认参数

    var opt = $.extend({}, defaults, options);

    //初始表格
    var init = function () {
        //alert(opt.Container);

        var oTable = document.createElement("table");


        var oThead = document.createElement("thead");
        for (var i = 0; i < opt.Columns.length; i++) {
            var col = opt.Columns[i];

            var oTh = document.createElement("th");
            oTh.innerText = opt.Columns[i].name;

            $(oTh).attr("style", col.style);

            oThead.appendChild(oTh);
        }
        oTable.appendChild(oThead);

        var oTbody = document.createElement("tbody");
        oTable.appendChild(oTbody);

        //底部行
        //        var oTfoot = document.createElement("tfoot");
        //        for (var i = 0; i < opt.Columns.length; i++) {
        //            var col = opt.Columns[i];

        //            var oTh = document.createElement("th");
        //            oTh.innerText = opt.Columns[i].name;
        //            $(oTh).attr("style", col.style);
        //            oTfoot.appendChild(oTh);
        //        }
        //        oTable.appendChild(oTfoot);


        opt.Container.append(oTable);
        opt.Table = oTable;

        $(oTable).attr("class", opt.Css);
    }

    //添加按钮
    var appendButtons = function (oTd, buttons) {
        for (var y = 0; y < buttons.length; y++) {
            var oButton = document.createElement("input");
            $(oButton).attr("type", "button");
            if (typeof buttons[y].event == "string")
                $(oButton).attr("class", buttons[y].event);
            else
                $(oButton).attr("class", "btn");

            oButton.value = buttons[y].name;

            //编辑按钮
            if (buttons[y].event == "edit") {
                $(oButton).click(function () {
                    editEvent($(this));
                });
            }
            //插入按钮
            if (buttons[y].event == "insert") {
                $(oButton).click(function () {
                    var row = insertRow(null);
                    row.data("rowstate", "new");  //编辑行状态

                    //插入
                    editEvent($("tbody tr:last-child", opt.Table));
                });
            }
            //删除按钮
            if (buttons[y].event == "delete") {
                $(oButton).click(function () {
                    var row = findRow($(this));
                    var oldData = $(row).data("datasource");
                    // alert(oldData);

                    //判断是否新添加数据行，如果是则不需要判断直接删除，否则通过委托调用
                    //委托处理
                    if (opt.deleteEvent != null && oldData != null) {
                        var data = getRowData(row);
                        opt.deleteEvent($(this), data);
                    }
                    else
                        row.remove();
                });
            }

            //调用委托
            if (typeof buttons[y].event == "function") {
                $(oButton).click({ delegateEvent: buttons[y].event }, function (event) {
                    var row = findRow($(this));
                    var data = $(row).data("datasource");
                    event.data.delegateEvent($(this), data);
                });
            }

            oTd.appendChild(oButton);
        }

        var saveButtons = [{ name: "保存", event: "save" }, { name: "取消", event: "cancel"}];
        for (var y = 0; y < saveButtons.length; y++) {
            var oButton = document.createElement("input");
            $(oButton).attr("type", "button");
            $(oButton).attr("class", saveButtons[y].event);
            $(oButton).hide();

            oButton.value = saveButtons[y].name;

            //取消事件
            if (saveButtons[y].event == "cancel") {
                $(oButton).click(function () {
                    //editEvent($(this));

                    //取消编辑，还原数据
                    var row = findRow($(this));
                    var data = $(row).data("datasource");
                    var rowstate = $(row).data("rowstate");

                    if (rowstate == "new")
                        row.remove();
                    else
                        fullRowData(row, data);
                });
            }
            //保存事件
            if (saveButtons[y].event == "save") {
                //提取行数据
                $(oButton).click(function () {
                    var row = findRow($(this));
                    var data = getRowData(row);

                    //委托处理
                    if (opt.saveEvent != null)
                        opt.saveEvent($(this), data);
                });
            }

            oTd.appendChild(oButton);
        }
    }

    //获取行数据，返回 json 格式数据
    var getRowData = function (row) {

        var objInputs = $("input:text,input:checkbox,select", row);
        var data = $(row).data("datasource");
        if (data == null) data = {};

        for (var i = 0; i < objInputs.length; i++) {
            var name = objInputs[i].name;

            if (objInputs[i].name == undefined) continue;
            var val = objInputs[i].value;

            //复选框类型值
            if (objInputs[i].type == "checkbox") {
                val = objInputs[i].checked ? "1" : "0";
            }

            eval("data." + name + " = '" + val + "'");
        }

        return data;
    }

    //取消编辑
    this.cancelEdit = function (src) {
        editEvent(src);
    }
    //删除指定行
    this.deleteRow = function (src) {
        var row = findRow(src);
        $(row).remove();
    }

    //查找映射的对象值  data = [{text:"",value:""}]
    var findMapValue = function (data, text, col) {
        for (var x = 0; x < data.length; x++) {
            if (col.mapTextFiled == undefined || col.mapTextFiled == "") {  //读取默认字段信息
                if (data[x].text == text)
                    return data[x].value;
            }
            else {
                if (eval("data[x]." + col.mapTextFiled) == text)
                    return eval("data[x]." + col.mapValueFiled);
            }
        }
        return "";
    }
    //根据索引取值
    var findMapValueByIndex = function (data, index, col) {
        if (col.mapTextFiled == undefined || col.mapTextFiled == "") {  //读取默认字段信息
            return data[index].value;
        }
        else {
            return eval("data[index]." + col.mapValueFiled);
        }

        return "";
    }

    //查找映射的对象文本
    var findMapText = function (data, value, col) {
        for (var x = 0; x < data.length; x++) {
            if (col.mapTextFiled == undefined || col.mapTextFiled == "") {  //读取默认字段信息
                if (data[x].value == value)
                    return data[x].text;
            }
            else {
                if (eval("data[x]." + col.mapValueFiled) == value)
                    return eval("data[x]." + col.mapTextFiled);
            }
        }
        return "";
    }
    //根据索引取文本
    var findMapTextByIndex = function (data, index, col) {
        if (col.mapTextFiled == undefined || col.mapTextFiled == "") {  //读取默认字段信息
            return data[index].text;
        }
        else {
            return eval("data[index]." + col.mapTextFiled);
        }

        return "";
    }

    //编辑行事件
    var editEvent = function (src) {
        var row = findRow(src);
        var editFlag = $(row).data("edit");
        var data = $(row).data("datasource");
        editFlag = !editFlag;
        $(row).data("edit", editFlag);

        //显示按钮
        if (editFlag) {  //编辑状态，显示保存以及取消按钮
            $(".edit", row).hide();
            $(".save", row).show();
            $(".cancel", row).show();
            $(".delete", row).hide();
        }
        else {
            $(".edit", row).show();
            $(".save", row).hide();
            $(".cancel", row).hide();
            $(".delete", row).show();
        }

        for (var i = 0; i < opt.Columns.length; i++) {
            var col = opt.Columns[i];
            var oTd = $($("td", row)[i]);

            if (col.type == "textbox" || col.type == "datetime") {

                if (editFlag) { //编辑状态                           
                    var ipt = document.createElement("input");
                    ipt.name = col.dataFiled;
                    ipt.type = "text";
                    ipt.className = "txt";
                    ipt.value = oTd.text();
                    oTd.text("");
                    oTd.append(ipt);

                    if (col.type == "textbox")
                        $(ipt).css("width", "98%");

                    //绑定日期选择器事件
                    if (col.type == "datetime" && opt.datePickerEvent != null)
                        opt.datePickerEvent(ipt);
                }
                else { //非编辑状态 
                    oTd.text(oTd.children().val());
                }
            }

            if (col.type == "checkbox") {
                if (editFlag) { //编辑状态     
                    //找出checkbox 对应的值
                    var text = oTd.text();
                    var val = findMapValue(col.data, text, col); //找出待显示的值

                    var ipt = document.createElement("input");
                    ipt.name = col.dataFiled;
                    ipt.type = "checkbox";
                    ipt.value = val;
                    if (val == "1")
                        $(ipt).attr("checked", "checked");

                    oTd.text("");
                    oTd.append(ipt);
                }
                else { //非编辑状态 
                    var val = oTd.children().attr("checked") ? "1" : "0";
                    var text = findMapText(col.data, val, col);

                    //alert(oTd.children().attr("checked"));
                    //alert(val);
                    //alert(text);
                    oTd.text(text);
                }
            }

            //下拉编辑框
            if (col.type == "dropdownlist") {
                if (editFlag) { //编辑状态     
                    //找出checkbox 对应的值
                    var text = oTd.text();
                    var val = findMapValue(col.data, text, col); //找出待显示的值

                    //动态创建下拉框
                    var ipt = document.createElement("select");
                    ipt.name = col.dataFiled;
                    for (var x = 0; x < col.data.length; x++) {
                        var option = document.createElement("option");
                        option.innerText = findMapTextByIndex(col.data, x, col);
                        option.value = findMapValueByIndex(col.data, x, col);

                        if (option.value == val)
                            option.selected = true;

                        ipt.appendChild(option);
                    }

                    oTd.text("");
                    oTd.append(ipt);
                    $(ipt).css("width", "98%");
                }
                else { //非编辑状态 
                    var val = oTd.children().val();
                    var text = findMapText(col.data, val, col);
                    oTd.text(text);
                }
            }
        }



    }
    //删除行事件
    var deleteEvent = function (src) {

    }
    //查找对象所在的行
    var findRow = function (obj) {
        while (obj[0].tagName != "TR")
            obj = obj.parent();
        return obj;
    }

    //格式化日期格式，/date(32098230832)/ 转换
    var formatDate = function (str) {
        if (str.indexOf("Date") != -1) {
            var d = str.substring(str.indexOf("(") + 1);
            d = d.substring(0, d.indexOf(")"));

            var date = new Date(parseInt(d));

            var str = "";
            str += date.getFullYear() + "-";
            str += (date.getMonth() + 1) + "-";
            str += date.getDate();
            return str;
        }
        else
            return str;
    }

    //给行填充数据
    var fullRowData = function (row, d) {


        $("td", row).remove();

        $(row).data("edit", false); //非编辑状态
        $(row).data("datasource", d);
        //添加列
        for (var n = 0; n < opt.Columns.length; n++) {
            var col = opt.Columns[n];
            var oTd = document.createElement("td");

            //赋值
            if (col.dataFiled != undefined && col.dataFiled != "" && d != undefined && d != null) {
                var value = eval("d." + col.dataFiled);

                if (col.type == "text" || col.type == "textbox")
                    oTd.innerText = value;

                if (col.type == "datetime")
                    oTd.innerText = formatDate(value);

                //找出复选框的text
                if (col.type == "checkbox" || col.type == "dropdownlist") {
                    var text = findMapText(col.data, value, col);
                    oTd.innerText = text;
                }
            }
            //添加按钮
            if (col.buttons != undefined && col.buttons.length != 0) {
                appendButtons(oTd, col.buttons);
            }

            $(row).append(oTd);
        }
    }

    //插入新行
    var insertRow = function (d) {
        var oTr = document.createElement("tr");
        $("tbody", opt.Table).append(oTr);

        fullRowData(oTr, d);  //填充数据
        $(oTr).data("rowstate", "edit");  //编辑行状态

        if (opt.dblclickToEdit) {  //双击进入编辑状态
            $(oTr).dblclick(function () {
                editEvent($(this));
            });
        }

        return $(oTr);
    }

    var bindJsonData = function (data) {
        $("tr", opt.Table).remove(); //移除原始数据
        opt.DataSource = data;

        for (var i = 0; i < data.length; i++) {
            var d = data[i]; //行数据
            insertRow(d);
        }
    }

    //重新加载数据
    this.reloadData = function () {
        if (opt.AjaxUrl != undefined && opt.AjaxUrl != null) {
            var url = opt.AjaxUrl;
            if (opt.AjaxUrl.indexOf("?") != -1)
                url += "&rnd=" + Math.random();
            else
                url += "?rnd=" + Math.random();

            //alert(opt.AjaxUrl);
            this.bindAjaxData(opt.AjaxUrl);
        }
        else
            this.bindAjaxData(opt.DataSource);
    }

    //绑定表格行数据  数据格式为 json 格式
    this.bindData = function (data) {
        bindJsonData(data);
    }

    //绑定表格行数据  通过ajax 请求数据绑定 数据格式为 json 格式
    this.bindAjaxData = function (url) {
        opt.AjaxUrl = url; //ajax请求的数据集合

        if (url.indexOf("?") != -1)
            url += "&rnd=" + Math.random();
        else
            url += "?rnd=" + Math.random();

        $.ajax({
            url: url,
            type: "get",
            dataType: "text",
            data: null,
            context: this,
            completed: function () { alert("complete") },
            success: function (result) {
                this.bindData(eval(result));
            },
            error: function (result, d, e) {
                alert("ajax error");
            }
        });
    }

    init();

    return this;
}